#include "ServerProtocol.hpp"

#include "Log.hpp"

dap::ServerProtocol::ServerProtocol(Socket::Ptr_t conn)
    : m_conn(conn)
{
}

dap::ServerProtocol::~ServerProtocol() {}

void dap::ServerProtocol::Initialize()
{
    // Attempt to read something from the network
    enum eState { kWaitingInitRequest, kDone };
    eState state = kWaitingInitRequest;
    while (state != kDone) {
        std::string network_buffer;
        if (m_conn->SelectReadMS(10) == dap::Socket::kSuccess) {
            if (m_conn->Read(network_buffer) == dap::Socket::kSuccess) {
                LOG_DEBUG1() << "Read: " << network_buffer << endl;

                // Append the buffer to what we already have
                m_rpc.AppendBuffer(network_buffer);

                // Try to construct a message and process it
                m_rpc.ProcessBuffer(
                    [&](Json json, wxObject*) {
                        dap::ProtocolMessage::Ptr_t request = ObjGenerator::Get().FromJSON(json);
                        if (request && request->type == "request" && request->As<dap::InitializeRequest>()) {
                            dap::InitializeResponse initResponse;
                            m_rpc.Send(initResponse, m_conn);
                            LOG_DEBUG() << "Sending InitializeRequest";

                            // Send InitializedEvent
                            dap::InitializedEvent initEvent;
                            m_rpc.Send(initEvent, m_conn);
                            LOG_DEBUG() << "Sending InitializedEvent";
                            LOG_INFO() << "Initialization completed";
                            state = kDone;
                        };
                    },
                    nullptr);
            }
        }
    }
}

void dap::ServerProtocol::Check()
{
    if (m_onNetworkMessage) {
        // First try to read something from the network
        std::string content;
        if (m_conn->SelectReadMS(10) == dap::Socket::kSuccess && m_conn->Read(content) == Socket::kSuccess) {
            m_rpc.AppendBuffer(content);
        }

        // Process it
        m_rpc.ProcessBuffer(
            [&](Json json, wxObject*) {
                dap::ProtocolMessage::Ptr_t message = ObjGenerator::Get().FromJSON(json);
                if (message) {
                    return m_onNetworkMessage(message);
                }
            },
            nullptr);
    }
}

void dap::ServerProtocol::ProcessGdbMessage(dap::ProtocolMessage::Ptr_t message)
{
    // message was generated by the GDB driver. Send it over to the client
    LOG_DEBUG() << "-->" << message->ToString();
    m_rpc.Send(message, m_conn);
}
